home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 283_01 / fafnir.h < prev    next >
Encoding:
C/C++ Source or Header  |  1988-12-08  |  20.0 KB  |  572 lines

  1. /* fafnir.h -- general purpose forms dragon, with Elysian Fields
  2.                5/10/88, 8/20/88, 9/10/88, 9/24/88, by d.c.oshel
  3.                */
  4.  
  5. /*========================================================================* 
  6. **  A FORM_RULES array defines a form.                                    **
  7. **                                                                        **
  8. **  All relevant information about a form and its fields is collected in  **
  9. **  the field elements of a FORM_RULES array.                             **
  10.  *========================================================================*/
  11.  
  12. typedef char * FPTR; /* pointer to a character array used for data entry */
  13.  
  14. #define FIELDS FPTR  /* for convenience in declaring field names */
  15.  
  16. typedef int (cdecl * VALIDATER)(); /* pointer to C function returning int */
  17.  
  18. #define VNOP ((VALIDATER)0)     /* "null function", validate not required */
  19.  
  20. /* NOTE: character validaters:  unsigned (*cv)( unsigned ch, int position );
  21.          field validaters:      int (*fv)( char *p, int x, int y, int len );
  22.          field initializers:    int (*fi)( char *p, int x, int y, int len );
  23.          */
  24.  
  25. typedef struct field_element {
  26.     FPTR *fptr;   /* the ADDRESS of a char * to this field's storage area */
  27.     FPTR dflt;    /* pointer to a default data entry mask for this field */
  28.     int x;        /* screen column of field, 0..79 */
  29.     int y;        /* screen line of field, 0..24 */
  30.     int len;      /* field width; if negative, width of window & field = 80 */
  31.     VALIDATER fi; /* pointer to each-time-arrived field initializer */
  32.                   /* if fi == VNOP, the field is not touched */
  33.     VALIDATER cv; /* pointer to character-by-character validation function */
  34.                   /* if cv == VNOP, the cursor does not stop in the field */
  35.     VALIDATER fv; /* pointer to each-time-exited field validation function */
  36.                   /* if fv == VNOP, the field is considered valid */
  37.  
  38. } FORM_RULES;
  39.  
  40. /* see EditField concerning variable length fields (len < 0), below */
  41.  
  42.  
  43. /*======================================================================*/
  44. /*             FORM_RULES macros for standard field types               */
  45. /*======================================================================*/
  46.  
  47. #define MAXVFLDLEN 80     /* longest variable length field */
  48. #define SLIDE(L) (-L)     /* marks window width for variable length field */
  49.  
  50. #define DEFINE_FIELDS(Q) FORM_RULES Q[] = {
  51. #define END_FIELDS };
  52. #define GetPage(SCREEN,NAME,OFFSET,NUMFLZ) SCREEN,&NAME[OFFSET],NUMFLZ 
  53. #define FormSize(F) (sizeof(F)/sizeof(FORM_RULES))
  54.  
  55. /* default edit masks */
  56.  
  57. #define TX_MASK NULL      /* text */
  58. #define DL_MASK zdol      /* dollar */
  59. #define PH_MASK zfone     /* phone */
  60. #define DT_MASK zdate     /* date */
  61. #define SN_MASK zssn      /* social security number */
  62. #define ZR_MASK zeroes    /* all zeroes */
  63. #define YN_MASK "N"       /* Yes or No */
  64.  
  65. #define DL_SIZE 15
  66. #define PH_SIZE 14
  67. #define SN_SIZE 11
  68. #define TZ_SIZE 10
  69. #define DT_SIZE 8
  70. #define ZP_SIZE 5
  71. #define YN_SIZE 1
  72. #define TF_SIZE YN_SIZE
  73. #define ST_SIZE 2
  74. #define CO_SIZE 2
  75.  
  76. #define TOP_OF_FORM 0 
  77.  
  78. #define UPDATE 1   /* see Example, below */
  79. #define ADD 0      /* see Example, below */
  80.  
  81. /* the following macros reduce the field definition task to simple lists */
  82.  
  83. #define FIELD(F,M,X,Y,L,I,C,V)  {&F,M,X,Y,L,I,C,V},  /* generic macro */
  84.  
  85.             /*------------------------------------------*/
  86.             /*  F  field name                           */
  87.             /*  M  default field mask, i.e., contents   */
  88.             /*  X  screen column                        */
  89.             /*  Y  screen row                           */
  90.             /*  L  field length, i.e., width            */
  91.             /*  I  field initialization, VALIDATER name */
  92.             /*  C  character validation, VALIDATER name */
  93.             /*  V  field validation, VALIDATER name     */
  94.             /*------------------------------------------*/
  95.  
  96.             /*     Example of editing a prior record:
  97.             *
  98.             *      FIELDS lastname, firstnam, fullname, homephon;
  99.             *
  100.             *      DEFINE_FIELDS( edits_record )
  101.             *         TEXT(      lastname, 10, 2, 15               )
  102.             *         TEXT(      firstnam, 10, 3, 15               )
  103.             *         VIRTUAL(   fullname, 10, 5, 30, concatnames  )
  104.             *         PHONE_SET( homephon, "(319) 555-    ", 10, 7 )
  105.             *      END_FIELDS;
  106.             *
  107.             *      #define ALL 4
  108.             *
  109.             *      AllocateFields( edits_record, ALL );
  110.             *      <--find previous record and load fields because UPDATE-->
  111.             *      action = OnePageForm( 
  112.             *               GetPage( edits_record, TOPF, ALL_FIELDS ),
  113.             *               UPDATE
  114.             *               );
  115.             *      <--save/ignore edits, etc., based on action-->
  116.             *      ReleaseFields( edits_record, ALL );
  117.             */
  118.  
  119.             /* Note macro syntax: use "NAME( ", not "NAME ("
  120.             *  do not put trailing commas after ) in field type macros.
  121.             */
  122.  
  123.             /* WARNING: the NumFields dimension is ** CRITICAL **
  124.             *           in AllocateFields!  Potential system crash.
  125.             */
  126.  
  127.             /* WARNING: routines to load fields must pad right
  128.             *           with blanks, and honor field width!
  129.             */
  130.  
  131.  
  132. /* standard text field definitions */
  133.  
  134. #define TEXT(F,X,Y,L)         {&F,TX_MASK,X,Y,L,VNOP,cgood,VNOP},
  135. #define UPPER(F,X,Y,L)        {&F,TX_MASK,X,Y,L,VNOP,c2upr,VNOP},
  136.  
  137. #define TEXT_SET(F,M,X,Y,L)   {&F,M,X,Y,L,VNOP,cgood,VNOP},
  138. #define UPPER_SET(F,M,X,Y,L)  {&F,M,X,Y,L,VNOP,c2upr,VNOP},
  139.  
  140.  
  141. /* masked numeric input, L <= 10, R is a VALIDATER for range checking */
  142.  
  143. #define ZERO(F,X,Y,L,R)       {&F,ZR_MASK,X,Y,L,VNOP,cnmrc,R},
  144. #define ZERO_SET(F,M,X,Y,L,R) {&F,M,X,Y,L,VNOP,cnmrc,R},
  145.  
  146.  
  147. /* standard fields with pre-determined widths */
  148.  
  149. #define DOLLAR(F,X,Y)         {&F,DL_MASK,X,Y,DL_SIZE,lj_dol,cdoll,rj_dol},
  150. #define PHONE(F,X,Y)          {&F,PH_MASK,X,Y,PH_SIZE,VNOP,cfone,VNOP},
  151. #define SSN(F,X,Y)            {&F,SN_MASK,X,Y,SN_SIZE,VNOP,cnmrc,VNOP},
  152. #define DATE(F,X,Y)           {&F,DT_MASK,X,Y,DT_SIZE,VNOP,cnmrc,vdate},
  153. #define ZIP(F,X,Y)            {&F,ZP_MASK,X,Y,YN_SIZE,VNOP,cnmrc,VNOP},
  154. #define TENZIP(F,X,Y)         {&F,TZ_MASK,X,Y,TZ_SIZE,VNOP,cnzip,VNOP},
  155.  
  156. #define YESNO(F,X,Y)          {&F,"Y",X,Y,TF_SIZE,VNOP,ctfyn,vtrufal},
  157. #define NOYES(F,X,Y)          {&F,"N",X,Y,TF_SIZE,VNOP,ctfyn,vtrufal},
  158.  
  159. #define DOLLAR_SET(F,M,X,Y)   {&F,M,X,Y,DL_SIZE,lj_dol,cdoll,rj_dol},
  160. #define PHONE_SET(F,M,X,Y)    {&F,M,X,Y,PH_SIZE,VNOP,cfone,VNOP},
  161. #define SSN_SET(F,M,X,Y)      {&F,M,X,Y,SN_SIZE,VNOP,cnmrc,VNOP},
  162. #define DATE_SET(F,M,X,Y)     {&F,M,X,Y,DT_SIZE,VNOP,cnmrc,vdate},
  163. #define ZIP_SET(F,M,X,Y)      {&F,M,X,Y,YN_SIZE,VNOP,cnmrc,VNOP},
  164. #define TENZIP_SET(F,M,X,Y)   {&F,M,X,Y,TZ_SIZE,VNOP,cnzip,VNOP},
  165.  
  166.  
  167. /* standard two-letter U.S. state and territory abbreviations */
  168.  
  169. #define STATE_SET(F,M,X,Y)    {&F,M,X,Y,ST_SIZE,VNOP,c2upr,vstate},
  170.  
  171.  
  172. /* Iowa Dept. of Transportation numeric county codes */
  173.  
  174. #define COUNTY_SET(F,M,X,Y)   {&F,M,X,Y,CO_SIZE,VNOP,cnmrc,vcounty},
  175.  
  176.  
  177. /* information-only field types */
  178.  
  179. #define TODAY(F,X,Y)             {&F,NULL,X,Y,DT_SIZE,vtoday,VNOP,VNOP},
  180.  
  181. #define DISPLAY(F,X,Y,L)         {&F,NULL,X,Y,L,VNOP,VNOP,VNOP},
  182. #define VIRTUAL(F,X,Y,L,A)       {&F,NULL,X,Y,L,A,VNOP,VNOP}, /* (*fi)() does it! */
  183. #define COMPUTE(F,X,Y,L,B)       {&F,NULL,X,Y,L,VNOP,VNOP,B}, /* (*fv)() does it! */
  184.  
  185. #define DISPLAY_SET(F,M,X,Y,L)   {&F,M,X,Y,L,VNOP,VNOP,VNOP},
  186. #define VIRTUAL_SET(F,M,X,Y,L,A) {&F,M,X,Y,L,A,VNOP,VNOP}, /* (*fi)() does it! */
  187. #define COMPUTE_SET(F,M,X,Y,L,B) {&F,M,X,Y,L,VNOP,VNOP,B}, /* (*fv)() does it! */
  188.  
  189.  
  190. /* INITIALIZE is a dummy (and costly!) secondary reference to a field.
  191.  
  192.    The idea is to get a field which is not immediately used into the range 
  193.    of fields allocated and/or initialized by AllocateFields or InitForm,
  194.    even though EditForm's range of fields deliberately excludes or includes
  195.    the field elsewhere, where it might be defined as TEXT(F,M,X,Y,L), etc.,
  196.    depending on circumstances.
  197.  
  198.    There is some overhead for including the INITIALIZE macro, so it should
  199.    be used sparingly, if at all.  FORM_RULES arrays can generally be
  200.    designed (or rearranged!) so that INITIALIZE is not necessary.
  201.    */
  202.  
  203. #define INITIALIZE(F,M,L)     {&F,M,0,0,L,VNOP,VNOP,VNOP},
  204.  
  205. /*=========================== end of field macros ======================*/
  206.  
  207.  
  208. /*------------------------*/
  209. /* EditForm Return Values */
  210. /*------------------------*/
  211.  
  212. /* this constant is defined, but it is not returned by anything
  213. */
  214.  
  215. #define EDIT_FORM 0   
  216.  
  217. /* these constants are returned by EditForm, OnePageForm, TwoPageForm */
  218.  
  219. #define SAVE_FORM 1
  220. #define SKIP_FORM 2
  221. #define DELETE_FORM 3
  222. #define STOP_SEARCH 4
  223.  
  224. /* note that EditForm can also return three keys: PGUP, PGDN, END */
  225. /* note that EditField returns the values of keys; see below */
  226.  
  227.  
  228.  
  229. /* skip flag used by EditField, NO_SKIP needs Enter to exit from a field */
  230.  
  231. #define SKIP_OK 1
  232. #define NO_SKIP 0
  233.  
  234.  
  235.  
  236. /* form skip flag used by EditForm, SINGLEPAGE needs Esc to exit from form */
  237.  
  238. #define SINGLEPAGE 0
  239. #define MULTIPAGE 1
  240.  
  241.  
  242.  
  243.  
  244. /* =====  Common Default Field Masks  ===== */
  245.  
  246. extern char zssn[];     /* "000-00-0000" */
  247. extern char zdate[];    /* "00/00/00" */
  248. extern char zfone[];    /* "(   )    -    " */
  249. extern char zeroes[];   /* "0000000000", ten zeroes */
  250. extern char zdol[];     /* "0.00" */
  251.  
  252. extern char *Fafnir_form_exit_actions[];  /* 3 is max! GLOBAL, 12/4/88, dco */
  253.  
  254. /* two useful lists */
  255.  
  256. extern char *states[];   /* in vstate.c  */
  257. extern char *counties[]; /* in vcounty.c */
  258.  
  259.  
  260.  
  261.  
  262. /* ====== bomb0(): A good global system error handler ======= */
  263.  
  264. typedef void (cdecl * PTR_TO_CRASH_FN)(void);
  265.  
  266. #define NO_CRASH_FN ((PTR_TO_CRASH_FN)0)
  267.  
  268. /* Fafnir's suggested system error handler will call the user's crash 
  269.    function if one has been set, then call vid_exit(), then vprintf(msg,...) 
  270.    at the bottom of the screen, then unconditionally exit(255)
  271.  
  272.    when called, bomb0() TERMINATES the program with errorlevel 255
  273.  
  274.    -----------------------------------------
  275.    NOTICE: user may #define bomb(X) bomb0(X)  <-- harmless, upward compatible
  276.    -----------------------------------------
  277.    */
  278. extern void bomb0( char *msg, ... );
  279.  
  280.  
  281. /* sample call:  set_crash_function( abnormal_shutdown )
  282.                  bomb0("out of memory"); 
  283.  
  284.    if bomb0() is called, user's abnormal_shutdown() function will be called
  285.    first, before bomb0() does anything else (such as printing the diagnostic)
  286.  
  287.    if set_crash_function() has not been called, no (*call_on_crash)() will
  288.    be executed; i.e., if not set the crash function is defined as a NOOP
  289.    */
  290. extern void set_crash_function( PTR_TO_CRASH_FN call_on_crash );
  291.  
  292.  
  293.  
  294. /* user should call this function on program exit to ensure field integrity;
  295.    it is possible to overwrite field buffers, since field char *'s are not
  296.    hidden from the user; calls bomb0() if programmer error can be detected
  297.    */
  298. extern void exit_fafnir( void );
  299.  
  300.  
  301.  
  302.  
  303. /* ========== Common Character Validater Functions =========== */
  304.  
  305. extern unsigned cgood( unsigned c ); /* any printable ASCII char */
  306. extern unsigned c2upr( unsigned c ); /* uppercase alpha, else like cgood */
  307. extern unsigned cnmrc( unsigned c ); /* digits 0..9 only */
  308.  
  309. /* two "free-form numeric" character validaters, allow blank field */
  310. extern unsigned cnzip( unsigned c ); /* space, hyphen (or minus), 0..9 only */
  311. extern unsigned cdoll( unsigned c ); /* dollar, i.e., $12,345,678.90- and space */
  312.  
  313. /* fills "(   )    -    " zfone mask with "(123) 678-ABCD", alphanumerics */
  314. extern unsigned cfone( unsigned c, int pos );
  315.  
  316. /* returns 'Y' or 'N' on T,t,Y,y,1 or N,n,F,f,0 */
  317. unsigned ctfyn( unsigned c );
  318.  
  319.  
  320. /* ========== Common Field Validater Functions =========== */
  321.  
  322.  
  323. /* the FORM_RULE "{ &fptr, zblank, X, Y, 15, lj_dol, cdoll, rj_doll }"
  324. ** makes a very nice description of a DOLLAR type data entry field!
  325. */
  326. extern int rj_dol ( char *p, int x, int y, int len ); /* rightjustify $0.00 */
  327. extern int lj_dol ( char *p, int x, int y, int len ); /* leftjustify  $0.00 */
  328.  
  329. /* dates
  330. */
  331. extern int vdate( char *p, int x, int y, int len ); /* valid date string? */
  332. extern int vtoday( char *p, int x, int y, int len ); /* set p <- today's date */
  333.  
  334. /* state and county lists
  335. */
  336. extern int vstate( char *p, int x, int y, int len );  /* U.S. state abbrvs. */
  337. extern int vcounty( char *p, int x, int y, int len ); /* Iowa DOT county codes */
  338.  
  339. /* boolean
  340. */
  341. extern int vtrufal( char *p, int x, int y, int len ); /* Y or N */
  342.  
  343.  
  344. /* ======= Global Utility Functions ========= */
  345.  
  346.  
  347. /* returns the value of len (or fewer) digits in p as a signed short int
  348.    */
  349. extern int atoin( char *p, int len );
  350.  
  351.  
  352.  
  353. /* returns the value of len (or fewer) digits in p as a signed long int
  354.    */
  355. extern long atoln( char *p, int len );
  356.  
  357.  
  358.  
  359. /* atodoln() returns the value of len (or fewer) digits in p as a signed 
  360.    "dollar long" int; i.e., the string "$1.00" returns 100L, normalized
  361.    as n dollars * (100 cents/dollar).  Value may be negative!  A hyphen
  362.    anywhere in the string (normally leading or trailing) yields negative.
  363.  
  364.    atodoln() allows free-form user cents fields (!), i.e., 
  365.    $100 is $100. is $100.0 is $100.00 is $100.000 (mills digit truncated!)
  366.    all these cases return (long) 10000 cents, equivalent to $100.00
  367.    */
  368. extern long atodoln( char *p, int len );
  369.  
  370.  
  371.  
  372.  
  373. /* a useful date macro, needs char * to "MM/DD/YY" string,
  374. ** evaluates to a ((long) julian_date), must #include "ciao.h" to use it
  375. */
  376.  
  377. #define str2jul(D) (mdy2jul((atoin((D),2)),(atoin((D)+3,2)),(atoin((D)+6,2)+1900)))
  378.  
  379.  
  380.  
  381.  
  382. /* display a timed popout message
  383. */
  384. extern void boxmsg( char *msg, ... ); 
  385.  
  386.  
  387.  
  388. /* like boxmsg(), but not timed and overwrites current screen (!)
  389. */
  390. extern void nboxmsg( char *msg, ... ); 
  391.  
  392.  
  393.  
  394. /* a macro for menus */
  395. #define SIZE(CANARY) (sizeof(CANARY)/sizeof(char *))
  396.  
  397.  
  398. /* present a scrollbar menu of choices to the user,
  399. ** saves and restores screen and cursor,
  400. ** returns an int representing menu offset from 0 among the selections
  401. */
  402. extern int select( int topx, int topy, char *menu[], int menu_size ); 
  403.  
  404.  
  405. /* same as select, but does not save screen or cursor 
  406. */
  407. extern int select0( int topx, int topy, char *menu[], int menu_size );
  408.  
  409.  
  410.  
  411. /* saves screen, 
  412.    sprintf's up to 127-byte string from msg, ... 
  413.    executes (*fn)( string ), 
  414.    restores screen, 
  415.    returns the (*fn)() return value 
  416.    */
  417. extern unsigned screenroutine( unsigned (*fn)(char *), char *msg,... );
  418.  
  419.  
  420. /* =================== Prepare Screens, Display Forms ==================== */
  421.  
  422.  
  423. /* PrepScreen() reads a 4000-byte screen file from disk to a buffer, and 
  424.    returns a char far * to the buffer which contains the screen.
  425.  
  426.    Screen files must be created using ES.EXE, or any similar program which
  427.    writes video text page 0 to a disk file.
  428.    */
  429.  
  430. extern char far * PrepScreen( char *screen );
  431.  
  432.  
  433. /* PopScreen() copies the buffer set by PrepScreen() onto the screen
  434.    */
  435. extern void PopScreen( char far *p );
  436.  
  437.  
  438. /* DisplayForm returns nothing, assumes PrepScreen has been called to
  439. ** load a screen file, and that screen points to a buffer with screen image
  440. */
  441.  
  442. extern void DisplayForm( char far *screen, FORM_RULES form[], int NumFields );
  443.  
  444.  
  445.  
  446.  
  447. /* ======== *** MUST CALL *** Functions to Initialize a Form ============ */
  448.  
  449.  
  450. /* Dynamically allocates the indicated range of fields in a form,
  451.    and initializes each to a null-terminated string of len blanks;
  452.    if the dflt pointer is not NULL, installs the field's DATA ENTRY MASK;
  453.    if the field cannot be allocated, calls bomb() and gives up;
  454.  
  455.    This is a *** MUST CALL *** if strings have not already been
  456.    assigned to the form's fptrs!  See also InitForm().
  457.    */
  458. extern void AllocateFields( FORM_RULES form[], int NumFields );
  459.  
  460.  
  461.  
  462. /* Copies up to len bytes of each field's default string into its 
  463.    actual field buffer, in the range of fields indicated; if the
  464.    default string is shorter than the field itself, the remainder of
  465.    the field is padded to len bytes with blanks.
  466.  
  467.    Used to install a form's DATA ENTRY MASKS into each of its fields,
  468.    so this is a *** MUST CALL *** if AllocateFields() was not called.
  469.    */
  470. extern void InitForm( FORM_RULES form[], int NumFields );
  471.  
  472.  
  473.  
  474. /* releases a form's dynamic memory allocation as set by AllocateFields;
  475.    does nothing if AllocateFields was not called
  476.    */
  477. extern void ReleaseFields( FORM_RULES form[], int NumFields );
  478.  
  479.  
  480.  
  481.  
  482. /* ================== Edit Functions ===================== */
  483.  
  484.  
  485. /* EditField returns KEY CONSTANTS as exit codes (defined in "keys.h"):
  486. **
  487. **                 ESC or CR
  488. **                 F2, END, PGDN, PGUP, UP, DN
  489. **
  490. ** exit keys F2..DN do NOT validate the field, and do NOT change its contents!
  491. ** exit keys Esc or Enter, however, DO validate, and DO update IFF valid!
  492. ** if the field is not valid, according to (*fvalid)(), does not exit
  493. ** 
  494. ** Note: if ((*cvalid)( SPC, i )) at all i, INS and DEL keys are enabled!
  495. ** Shift_F1 always displays current version information, without exiting
  496. **
  497. ** New, 9/24/88, d.c.oshel -- if (len < 0), the field is treated like a
  498. **               variable length field padded right with blanks in a
  499. **               buffer MAXVFLDLEN chars long.  The edit field becomes a
  500. **               window len wide which "slides" over the longer edit buffer.
  501. **
  502. **               CAUTION:  fldptr  * M U S T *  point to a string which
  503. **               contains MAXVFLDLEN characters or blanks!  If INS and DEL
  504. **               keys can't be enabled (space not allowed in all positions),
  505. **               the field is treated like an ordinary field len chars wide.
  506. */
  507.  
  508. extern unsigned EditField (char *fldptr,      /* data address */
  509.                            int x, int y,      /* screen coordinates */
  510.                            int len,           /* field length */ 
  511.                            int skip_to_next,  /* end-of-field handling flag */
  512.                            VALIDATER cvalid,  /* individual char validation */
  513.                            VALIDATER fvalid); /* whole field validation */
  514.  
  515.  
  516.  
  517. /*  EditForm returns these exit codes:       SAVE_FORM, SKIP_FORM,
  518. **  plus, IFF MultiPage:                     PGDN, PGUP,
  519. **  plus, IFF cursor did not stop anywhere:  END
  520. */
  521. extern unsigned EditForm ( FORM_RULES form[], int NumFields, int MultiPage );
  522.  
  523.  
  524.  
  525. /* ========== Screen Managers =========== */
  526.  
  527.  
  528. /*  _onepageform returns:  SAVE_FORM, SKIP_FORM
  529. **                         accepts a pointer to a screen buffer
  530. */
  531.  
  532. extern int _onepageform( char far *screen, FORM_RULES Page[], int NumFields );
  533.  
  534.  
  535.  
  536. /*  _twopageform returns:  SAVE_FORM, SKIP_FORM
  537. **                         accepts pointers to two screen buffers
  538. */
  539.  
  540. extern int _twopageform( char far *screen1, FORM_RULES Page1[], int NumFields1,
  541.                          char far *screen2, FORM_RULES Page2[], int NumFields2 );
  542.  
  543.  
  544. /*  OnePageForm returns:  SAVE_FORM, SKIP_FORM,
  545. **  plus, IFF OldRecord:  DELETE_FORM, STOP_SEARCH
  546. **
  547. **  accepts the name of a screen file, gives opening dialogue if the
  548. **  OldRecord flag is true
  549. **
  550. **  assumes fields are Allocated, and either cleared or pre-loaded (OldRecord)
  551. */
  552. extern int OnePageForm( char *ScreenFileName, FORM_RULES Page[], 
  553.                         int NumFields, 
  554.                         int OldRecord );
  555.  
  556.  
  557. /*  TwoPageForm returns:  SAVE_FORM, STOP_SEARCH,
  558. **  plus, IFF OldRecord:  SKIP_FORM, DELETE_FORM
  559. **
  560. **  accepts the names of two screen files, gives opening dialogue if the
  561. **  OldRecord flag is true
  562. **
  563. **  assumes fields are Allocated, and either cleared or pre-loaded (OldRecord)
  564. */
  565. extern int TwoPageForm( char *ScreenFileName1, FORM_RULES Page1[], 
  566.                         int NumFields1,
  567.                         char *ScreenFileName2, FORM_RULES Page2[], 
  568.                         int NumFields2, 
  569.                         int OldRecord );
  570.  
  571.  
  572.